package com.m3958.logcollector;

import java.awt.Color;

import javax.sql.DataSource;

import org.flywaydb.core.Flyway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.acls.AclPermissionEvaluator;
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
import org.springframework.security.acls.domain.AuditLogger;
import org.springframework.security.acls.domain.ConsoleAuditLogger;
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
import org.springframework.security.acls.domain.SpringCacheBasedAclCache;
import org.springframework.security.acls.jdbc.BasicLookupStrategy;
import org.springframework.security.acls.jdbc.JdbcMutableAclService;
import org.springframework.security.acls.jdbc.LookupStrategy;
import org.springframework.security.acls.model.AclCache;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.PermissionGrantingStrategy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.github.bingoohuang.patchca.color.SingleColorFactory;
import com.github.bingoohuang.patchca.custom.ConfigurableCaptchaService;
import com.github.bingoohuang.patchca.filter.predefined.CurvesRippleFilterFactory;
import com.github.bingoohuang.patchca.font.RandomFontFactory;
import com.github.bingoohuang.patchca.text.renderer.BestFitTextRenderer;
import com.github.bingoohuang.patchca.word.AdaptiveRandomWordFactory;
import com.m3958.logcollector.vo.RoleNames;
import com.m3958.logcollector.vo.RoleVo;

/**
 * @author jianglibo@gmail.com
 *         2015年12月8日
 *
 */

@EnableScheduling
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.m3958.datacommons", "com.m3958.logcollector", "org.activiti.spring"})
public class Application extends WebMvcConfigurerAdapter {
    
    @Autowired
    private DataSource dataSource;
    
//    @Bean
//    public FlywayMigrationInitializer flywayInitializer(Flyway flyway, FlywayProperties properties) {
//        String[] los = new String[]{};
//        flyway.setLocations(properties.getLocations().toArray(los));
//        return new FlywayMigrationInitializer(flyway);
//    }
    
    @Bean
    public ConfigurableCaptchaService configurableCaptchaService() {
        ConfigurableCaptchaService cs = new ConfigurableCaptchaService();
        cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170)));
        cs.setFilterFactory(new CurvesRippleFilterFactory(cs.getColorFactory()));
        RandomFontFactory ff = new RandomFontFactory();
        ff.setMinSize(24);
        ff.setMaxSize(24);
        AdaptiveRandomWordFactory arf = new AdaptiveRandomWordFactory();
        arf.setMinLength(5);
        arf.setMaxLength(5);
        cs.setWordFactory(arf);
        cs.setFontFactory(ff);

        BestFitTextRenderer textRenderer = new BestFitTextRenderer();
        textRenderer.setTopMargin(0);
        textRenderer.setBottomMargin(0);
        textRenderer.setLeftMargin(0);
        textRenderer.setRightMargin(0);
        cs.setTextRenderer(textRenderer);

        cs.setHeight(35);
        cs.setWidth(80);
        return cs;
    }
    
    @Bean
    public LookupStrategy lookupStrategy() {
            return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), auditLogger());
    }
    
    @Bean
    public AclAuthorizationStrategy aclAuthorizationStrategy() {
        GrantedAuthority ga0 = new RoleVo(RoleNames.ACL_OWNERSHIP);
        GrantedAuthority ga1 = new RoleVo(RoleNames.ACL_AUDITING);
        GrantedAuthority ga2 = new RoleVo(RoleNames.ACL_DETAIL);
        
        return new AclAuthorizationStrategyImpl(ga0, ga1, ga2);
    }
    
    @Bean
    public AclPermissionEvaluator aclPermissionEvaluator() {
        return new AclPermissionEvaluator(aclService());
    }
    
    @Bean
    public AclCache aclCache() {
        Cache cache = new ConcurrentMapCache("aclCache");
        return new SpringCacheBasedAclCache(cache,permissionGrantingStrategy(),aclAuthorizationStrategy());
    }
    
    @Bean
    public PermissionGrantingStrategy permissionGrantingStrategy() {
        return new DefaultPermissionGrantingStrategy(auditLogger());
    }
    
    @Bean
    public AuditLogger auditLogger() {
        return new ConsoleAuditLogger();
    }
    
    @Bean
    public MutableAclService aclService() {
        Cache cache = new ConcurrentMapCache("aclCache");
        AclCache aclCache = new SpringCacheBasedAclCache(cache,permissionGrantingStrategy(),aclAuthorizationStrategy());
        return new JdbcMutableAclService(dataSource, lookupStrategy() , aclCache);

    }

    
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // .setCachePeriod(600)
        // registry.addResourceHandler("/**")
        // .addResourceLocations("classpath:/static/dist/")
        // .resourceChain(true);

        registry.addResourceHandler("/llapp/**")//
                .addResourceLocations("classpath:/static/dist/")//
                .setCachePeriod(22896000)//
                .resourceChain(true);

        registry.addResourceHandler("/notapp/**")//
                .addResourceLocations("classpath:/static/notapp/")//
                .setCachePeriod(22896000)//
                .resourceChain(true);

        // registry.addResourceHandler("/assets/**")
        // .addResourceLocations("classpath:/static/dist/assets/")
        // .setCachePeriod(22896000)
        // .resourceChain(true);
        //
        // registry.addResourceHandler("/myassets/**")
        // .addResourceLocations("classpath:/static/dist/myassets/")
        // .setCachePeriod(22896000)
        // .resourceChain(true);
        //
        // registry.addResourceHandler("/fonts/**")
        // .addResourceLocations("classpath:/static/dist/fonts/")
        // .setCachePeriod(22896000)
        // .resourceChain(true);

        registry.addResourceHandler("/very-long-cache/**").addResourceLocations("classpath:/static/very-long-cache/").setCachePeriod(22896000)
                .resourceChain(true);
    }

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        // System.out.println("Let's inspect the beans provided by Spring Boot:");
        //
        // String[] beanNames = ctx.getBeanDefinitionNames();
        // Arrays.sort(beanNames);
        // for (String beanName : beanNames) {
        // System.out.println(beanName);
        // }
    }
}
